package com.boboPlanet.comm.rabbitmq.consume;

import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

/**
 * @Description: TODO 消费者返回给生产者的消息确认回调
 * @Author: mis_wu
 * @Date: 2023/7/11
 * @Company planet
 **/
@Slf4j
@Component
public class MsgConfirmCallBackImpl implements RabbitTemplate.ConfirmCallback {

    @Resource
    private RabbitTemplate rabbitTemplate;

    @PostConstruct
    public void init(){
        //todo: 注入，因为此回调方法是RabbitTemplate.ConfirmCallback的内部方法，需手动注入，否则该实现类不生效
        rabbitTemplate.setConfirmCallback(this);
//        rabbitTemplate.setReturnCallback(this);
    }

    /**
     * todo: 消息确认回调方法
     * @param correlationData correlation data for the callback. 确认消息数据
     * @param ack true for ack, false for nack 交换机是否接收成功  true:成功   false:失败
     * @param cause An optional cause, for nack, when available, otherwise null. 失败原因  如果成功则为null
     */
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        String msgId = correlationData == null ? "" : correlationData.getId();
//        assert correlationData != null;
//        String traceId = (String) Objects.requireNonNull(correlationData.getReturnedMessage()).getMessageProperties().getHeaders().get(PlanetCommCode.COMM_LOG_KEY.getCode());
//
//        ThreadMdcUtil.setTraceId(traceId);

        if (ack){
            log.info("msg consume success,ack is true,then message id is :{}",msgId);
        }else {
            log.error("msg consume fail,ack is false,then message id is: {}, error reason is: {}",msgId,cause);
        }
    }

    /**
     * todo: 队列出现错误消息无法接收，需要回退消息，告诉生产者哪个消息无法被消费
     * @param message the returned message. 消息体
     * @param replyCode the reply code. 回退编码
     * @param replyText the reply text. 回退原因
     * @param exchange the exchange. 交换机
     * @param routingKey the routing key. 路由key
     */
    public void returnedMessage(Message message, int replyCode, @NotNull String replyText, @NotNull String exchange, @NotNull String routingKey) {
        String msgBody = new String(message.getBody());
        log.error("message consume fail,msg body is: {}",msgBody);
        log.error("message consume fail,reply code is: {}, reply reason is: {}",replyCode,replyText);
        log.error("message consume fail,error exchange is: {}, routing key is: {}",exchange,routingKey);

        //todo: 重新消费

    }
}
